package parser

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// TestStatementClassification 测试语句分类功能
func TestStatementClassification(t *testing.T) {
	tests := []struct {
		name     string
		sql      string
		expected StatementType
	}{
		// 数据库操作
		{"CREATE DATABASE", "CREATE DATABASE test;", CreateDatabase},
		{"DROP DATABASE", "DROP DATABASE test;", DropDatabase},
		{"USE DATABASE", "USE test;", UseDatabase},
		
		// 表操作
		{"CREATE TABLE", "CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));", CreateTable},
		{"DROP TABLE", "DROP TABLE users;", DropTable},
		
		// 索引和视图
		{"CREATE INDEX", "CREATE INDEX idx_name ON users(name);", CreateIndex},
		{"CREATE UNIQUE INDEX", "CREATE UNIQUE INDEX idx_email ON users(email);", CreateIndex},
		{"CREATE VIEW", "CREATE VIEW active_users AS SELECT * FROM users WHERE active = 1;", CreateView},
		
		// 存储过程和函数
		{"CREATE PROCEDURE", "CREATE PROCEDURE GetUser() BEGIN SELECT * FROM users; END;", CreateProcedure},
		{"CREATE FUNCTION", "CREATE FUNCTION GetUserCount() RETURNS INT BEGIN RETURN (SELECT COUNT(*) FROM users); END;", CreateFunction},
		{"CREATE TRIGGER", "CREATE TRIGGER user_audit AFTER INSERT ON users FOR EACH ROW INSERT INTO audit_log VALUES (NEW.id);", CreateTrigger},
		
		// 数据操作
		{"INSERT", "INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');", Insert},
		
		// 序列
		{"CREATE SEQUENCE", "CREATE SEQUENCE user_id_seq START WITH 1 INCREMENT BY 1;", CreateSequence},
		
		// 分隔符
		{"DELIMITER", "DELIMITER //", Delimiter},
		
		// 其他有效SQL语句
		{"UPDATE", "UPDATE users SET name='李四' WHERE id=1;", Other},
		{"DELETE", "DELETE FROM users WHERE id=1;", Other},
		{"ALTER TABLE", "ALTER TABLE users ADD COLUMN age INT;", Other},
		{"SELECT", "SELECT * FROM users;", Other},
		
		// 未知或无效语句
		{"COMMENT", "-- This is a comment", Unknown},
		{"BLOCK COMMENT", "/* This is a block comment */", Unknown},
		{"EMPTY", "", Unknown},
		{"WHITESPACE", "   \t\n  ", Unknown},
	}
	
	parser := NewMySQLParser()
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := parser.classifyStatement(tt.sql)
			if result != tt.expected {
				t.Errorf("classifyStatement(%q) = %v, want %v", tt.sql, result, tt.expected)
			}
		})
	}
}

// TestGetStatementTypeName 测试语句类型名称获取
func TestGetStatementTypeName(t *testing.T) {
	tests := []struct {
		stmtType StatementType
		expected string
	}{
		{CreateDatabase, "CREATE_DATABASE"},
		{DropDatabase, "DROP_DATABASE"},
		{UseDatabase, "USE"},
		{CreateTable, "CREATE_TABLE"},
		{DropTable, "DROP_TABLE"},
		{CreateIndex, "CREATE_INDEX"},
		{CreateView, "CREATE_VIEW"},
		{CreateProcedure, "CREATE_PROCEDURE"},
		{CreateFunction, "CREATE_FUNCTION"},
		{CreateTrigger, "CREATE_TRIGGER"},
		{Insert, "INSERT"},
		{CreateSequence, "CREATE_SEQUENCE"},
		{Delimiter, "DELIMITER"},
		{Other, "OTHER"},
		{Unknown, "UNKNOWN"},
	}
	
	for _, tt := range tests {
		t.Run(tt.expected, func(t *testing.T) {
			result := GetStatementTypeName(tt.stmtType)
			if result != tt.expected {
				t.Errorf("GetStatementTypeName(%v) = %q, want %q", tt.stmtType, result, tt.expected)
			}
		})
	}
}

// TestStatisticsUpdate 测试统计信息更新
func TestStatisticsUpdate(t *testing.T) {
	parser := NewMySQLParser()
	
	// 测试各种语句类型的统计
	testCases := []struct {
		stmtType StatementType
		statKey  string
	}{
		{CreateDatabase, "数据库"},
		{CreateTable, "表"},
		{CreateIndex, "索引"},
		{CreateView, "视图"},
		{CreateProcedure, "存储过程"},
		{CreateFunction, "函数"},
		{CreateTrigger, "触发器"},
		{Insert, "插入语句"},
		{CreateSequence, "序列"},
		{Other, "其他语句"},
		{Unknown, "未知语句"},
	}
	
	for _, tc := range testCases {
		parser.updateStats(tc.stmtType)
	}
	
	stats := parser.GetStats()
	
	// 验证每种类型的统计都是1
	for _, tc := range testCases {
		if count := stats[tc.statKey]; count != 1 {
			t.Errorf("Expected %s count to be 1, got %d", tc.statKey, count)
		}
	}
	
	// 验证总语句数
	expectedTotal := len(testCases)
	if totalCount := stats["总语句数"]; totalCount != expectedTotal {
		t.Errorf("Expected total statement count to be %d, got %d", expectedTotal, totalCount)
	}
}

// TestParseEmptyFile 测试解析空文件
func TestParseEmptyFile(t *testing.T) {
	// 创建临时空文件
	tempFile := filepath.Join(os.TempDir(), "empty_test.sql")
	defer os.Remove(tempFile)
	
	file, err := os.Create(tempFile)
	if err != nil {
		t.Fatalf("Failed to create temp file: %v", err)
	}
	file.Close()
	
	parser := NewMySQLParser()
	stmts, err := parser.Parse(tempFile)
	
	if err != nil {
		t.Errorf("Expected no error for empty file, got: %v", err)
	}
	
	if len(stmts) != 0 {
		t.Errorf("Expected 0 statements for empty file, got %d", len(stmts))
	}
}

// TestParseNonExistentFile 测试解析不存在的文件
func TestParseNonExistentFile(t *testing.T) {
	parser := NewMySQLParser()
	_, err := parser.Parse("/non/existent/file.sql")
	
	if err == nil {
		t.Error("Expected error for non-existent file, got nil")
	}
}

// TestParseWithComments 测试解析包含注释的文件
func TestParseWithComments(t *testing.T) {
	// 创建临时文件
	tempFile := filepath.Join(os.TempDir(), "comments_test.sql")
	defer os.Remove(tempFile)
	
	content := `-- 这是注释
CREATE DATABASE test;
/* 多行注释
   继续注释 */
USE test;
-- 另一个注释
CREATE TABLE users (id INT);`
	
	file, err := os.Create(tempFile)
	if err != nil {
		t.Fatalf("Failed to create temp file: %v", err)
	}
	defer file.Close()
	
	_, err = file.WriteString(content)
	if err != nil {
		t.Fatalf("Failed to write to temp file: %v", err)
	}
	file.Close()
	
	parser := NewMySQLParser()
	stmts, err := parser.Parse(tempFile)
	
	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}
	
	// 应该只有3个有效语句（忽略注释）
	expectedCount := 3
	if len(stmts) != expectedCount {
		t.Errorf("Expected %d statements, got %d", expectedCount, len(stmts))
	}
	
	// 验证语句类型
	expectedTypes := []StatementType{CreateDatabase, UseDatabase, CreateTable}
	for i, stmt := range stmts {
		if stmt.Type != expectedTypes[i] {
			t.Errorf("Statement %d: expected type %v, got %v", i, expectedTypes[i], stmt.Type)
		}
	}
}

// TestParseStreamWithDelimiter 测试包含 DELIMITER 的存储过程按自定义终止符分句
func TestParseStreamWithDelimiter(t *testing.T) {
    // 构造包含 DELIMITER // 的过程定义
    content := strings.Join([]string{
        "DELIMITER //",
        "CREATE PROCEDURE p_demo()",
        "BEGIN",
        "  SELECT 1;",
        "  SELECT 'a;b' as txt;",
        "END //",
        "DELIMITER ;",
    }, "\n")

    tempFile := filepath.Join(os.TempDir(), "delimiter_stream_test.sql")
    defer os.Remove(tempFile)
    f, err := os.Create(tempFile)
    if err != nil { t.Fatalf("Failed to create temp file: %v", err) }
    if _, err := f.WriteString(content); err != nil { t.Fatalf("Failed to write temp file: %v", err) }
    f.Close()

    p := NewMySQLParser()
    var stmts []SQLStatement
    err = p.ParseStream(tempFile, func(s SQLStatement) error {
        stmts = append(stmts, s)
        return nil
    })
    if err != nil { t.Fatalf("ParseStream error: %v", err) }

    // 期待单条 CREATE_PROCEDURE 语句
    if len(stmts) != 1 {
        t.Fatalf("Expected 1 statement, got %d", len(stmts))
    }
    if stmts[0].Type != CreateProcedure {
        t.Fatalf("Expected statement type CreateProcedure, got %v", stmts[0].Type)
    }
    // 语句内容不应包含自定义终止符或 DELIMITER 指令
    if strings.Contains(stmts[0].Content, "DELIMITER") || strings.Contains(stmts[0].Content, "//") {
        t.Fatalf("Statement content should not contain delimiter tokens: %q", stmts[0].Content)
    }
    // 语句应包含内部的分号语句
    if !strings.Contains(stmts[0].Content, "SELECT 1;") {
        t.Fatalf("Procedure body should contain internal semicolon statement")
    }
}

// TestCaseInsensitiveClassification 测试大小写不敏感的分类
func TestCaseInsensitiveClassification(t *testing.T) {
	tests := []struct {
		name string
		sql  string
	}{
		{"lowercase", "create database test;"},
		{"uppercase", "CREATE DATABASE TEST;"},
		{"mixed case", "Create Database Test;"},
		{"with spaces", "  CREATE   DATABASE   test  ;"},
	}
	
	parser := NewMySQLParser()
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := parser.classifyStatement(tt.sql)
			if result != CreateDatabase {
				t.Errorf("classifyStatement(%q) = %v, want %v", tt.sql, result, CreateDatabase)
			}
		})
	}
}

// TestClassificationCreateViewVariants 测试多种含MySQL选项的CREATE VIEW识别
func TestClassificationCreateViewVariants(t *testing.T) {
    parser := NewMySQLParser()
    cases := []string{
        "CREATE OR REPLACE VIEW v AS SELECT 1;",
        "CREATE ALGORITHM=UNDEFINED VIEW v AS SELECT 1;",
        "CREATE DEFINER=`root`@`%` VIEW v AS SELECT 1;",
        "CREATE SQL SECURITY DEFINER VIEW v AS SELECT 1;",
        "CREATE OR REPLACE ALGORITHM=MERGE DEFINER=user@host SQL SECURITY INVOKER VIEW v AS SELECT 1;",
    }
    for i, sql := range cases {
        got := parser.classifyStatement(sql)
        if got != CreateView {
            t.Errorf("case %d: expected CreateView, got %v", i, got)
        }
    }
}

// BenchmarkClassifyStatement 性能测试
func BenchmarkClassifyStatement(b *testing.B) {
	parser := NewMySQLParser()
	sql := "CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100), email VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);"
	
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		parser.classifyStatement(sql)
	}
}

// BenchmarkParse 解析性能测试
func BenchmarkParse(b *testing.B) {
	// 创建临时测试文件
	tempFile := filepath.Join(os.TempDir(), "benchmark_test.sql")
	defer os.Remove(tempFile)
	
	// 生成测试内容
	var content strings.Builder
	for i := 0; i < 100; i++ {
		content.WriteString("CREATE DATABASE test_db_" + string(rune(i)) + ";\n")
		content.WriteString("USE test_db_" + string(rune(i)) + ";\n")
		content.WriteString("CREATE TABLE users_" + string(rune(i)) + " (id INT, name VARCHAR(50));\n")
		content.WriteString("INSERT INTO users_" + string(rune(i)) + " VALUES (1, 'test');\n")
	}
	
	file, err := os.Create(tempFile)
	if err != nil {
		b.Fatalf("Failed to create temp file: %v", err)
	}
	defer file.Close()
	
	_, err = file.WriteString(content.String())
	if err != nil {
		b.Fatalf("Failed to write to temp file: %v", err)
	}
	file.Close()
	
	parser := NewMySQLParser()
	
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err := parser.Parse(tempFile)
		if err != nil {
			b.Fatalf("Parse failed: %v", err)
		}
	}
}

// TestStatementTypeValidation 测试语句类型验证（为未来扩展准备）
func TestStatementTypeValidation(t *testing.T) {
	validTypes := []StatementType{
		Unknown, CreateDatabase, DropDatabase, UseDatabase,
		CreateTable, DropTable, CreateIndex, CreateView,
		CreateProcedure, CreateFunction, CreateTrigger,
		Insert, CreateSequence, Delimiter, Other,
	}
	
	for _, stmtType := range validTypes {
		name := GetStatementTypeName(stmtType)
		if name == "" {
			t.Errorf("StatementType %v should have a name", stmtType)
		}
	}
}

// TestClassificationWithDefiner 测试带DEFINER的语句分类
func TestClassificationWithDefiner(t *testing.T) {
    parser := NewMySQLParser()
    cases := []struct{
        sql string
        expected StatementType
    }{
        {"CREATE DEFINER=root@% PROCEDURE test(IN a INT, OUT b INT) BEGIN SET b=a; END", CreateProcedure},
        {"CREATE DEFINER=`root`@`%` FUNCTION f1(a INT) RETURNS INT BEGIN RETURN a; END", CreateFunction},
        {"CREATE DEFINER=my@host TRIGGER trg BEFORE INSERT ON t FOR EACH ROW BEGIN SET @x=1; END", CreateTrigger},
    }
    for i, c := range cases {
        got := parser.classifyStatement(c.sql)
        if got != c.expected {
            t.Errorf("case %d: expected %v, got %v", i, c.expected, got)
        }
    }
}